//  weibo: http://weibo.com/xiaoqing28
//  blog:  http://www.alonemonkey.com
//
//  dump_wechatDylib.m
//  dump_wechatDylib
//
//  Created by 周启睿 on 2019/1/22.
//  Copyright (c) 2019年 周启睿. All rights reserved.
//

#import "dump_wechatDylib.h"
#import <CaptainHook/CaptainHook.h>
#import <UIKit/UIKit.h>
#import <Cycript/Cycript.h>
#import <MDCycriptManager.h>
#import <WebKit/WebKit.h>
#import <ReactiveObjC/ReactiveObjC.h>
#import "FLEXManager.h"
#import "CTBlockDescription.h"
#import "TTVTextConventTool.h"
#import "TTVLogger.h"
#import "TTVWebServerManage.h"
#import "UIView+Draw.h"
#import "UIView+Toast.h"



#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"

#define TTVGCDMainAfter(PER_SEC)         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)\
(PER_SEC * NSEC_PER_SEC)), dispatch_get_main_queue(), ^//block
//====================================================================
//MONKEYDEV_RESTORE_SYMBOL 恢复符号表
//MONKEYDEV_CLASS_DUMP 选项
//PRODUCT_BUNDLE_IDENTIFIER 打包签名/非法包校验
//MONKEYDEV_DEFAULT_BUNDLEID 想使用原来的bundle id进行重签
//====================================================================
//调用类的其他私有方法
void(^invokeSelector)(NSObject*,NSString*) = ^(NSObject* object,NSString* func_text) {
    __weak NSObject* self_obj = object;
    NSString* selector_funcname = func_text;
    if ([self_obj respondsToSelector:NSSelectorFromString(selector_funcname)]) {
        [self_obj performSelector:NSSelectorFromString(selector_funcname)];
    }
};

//判断当前类型
int(^classEqualToString)(NSObject*,NSString*) = ^(NSObject* object,NSString* className) {
    NSString* t_className = NSStringFromClass(object.class);
    if ([t_className isEqualToString:className]){
        return true;
    }
    return false;
};

//改变基础类型值
void (^invocationInstanceValue)(NSObject*,NSString*,NSInteger )= ^(NSObject* target,NSString* selectorName,NSInteger value){
    SEL selector = NSSelectorFromString(selectorName);
    if ([target respondsToSelector:selector]) {
        NSInteger appid = value;
        Class class = target.class;// NSClassFromString(className);
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[class instanceMethodSignatureForSelector:selector]];
        [invocation setSelector:selector];
        [invocation setTarget:target];
        [invocation setArgument:&appid atIndex:2];
        [invocation invoke];
    }
};
//====================================================================

CHConstructor{
    printf(INSERT_SUCCESS_WELCOME);
    
    //[UIScreen mainScreen].isCaptured
    

    
    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        
#ifndef __OPTIMIZE__
        CYListenServer(6666);

        MDCycriptManager* manager = [MDCycriptManager sharedInstance];
        [manager loadCycript:true];

        NSError* error;
        NSString* result = [manager evaluateCycript:@"UIApp" error:&error];
        DLog(@"result: %@", result);
        if(error.code != 0){
            DLog(@"error: %@", error.localizedDescription);
        }
#endif
        
        [TTVWebServerManage WebServeManage];
        [[FLEXManager sharedManager] showExplorer];
        
        
        [[[UIApplication sharedApplication] rac_signalForSelector:@selector(openURL:)] subscribeNext:^(RACTuple * _Nullable x) {
            DLog(@"schemes:%@",x.first);
        }];

//        UIButton* btn = [[UIButton alloc] init];
//        [btn setTitle:@"flex_flex" forState:UIControlStateNormal];
//        [keyWindow addSubview:btn];
//        [btn sizeToFit];
//        [[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
//            btn.selected = !btn.selected;
//            if(btn.isSelected){
//                [[FLEXManager sharedManager] showExplorer];
//            }
//            else{
//                [[FLEXManager sharedManager] hideExplorer];
//            }
//        }];
    }];

}

#pragma mark - 好猫
CHDeclareClass(JDPlayVideoController)
CHOptimizedMethod0(self, void, JDPlayVideoController,  delayShowAd){
}
//CHOptimizedMethod1(self, void, JDPlayVideoController,  playAtIndex,long long,arg1){
//    CHSuper1(JDPlayVideoController, playAtIndex, arg1);
//}
CHConstructor{
    CHLoadLateClass(JDPlayVideoController);
    CHClassHook0(JDPlayVideoController,  delayShowAd);
//    CHClassHook1(JDPlayVideoController,  playAtIndex);
}


#pragma mark -  番茄/小姐姐
//====================================================================
//====================================================================
#pragma mark 番茄去录屏警告
CHDeclareClass(NSNotificationCenter)
CHOptimizedMethod4(self, void, NSNotificationCenter, addObserver, id, arg1, selector, SEL, aSelector, name, NSNotificationName, aName, object, id, anObject){
    if (@available(iOS 11.0, *)) {
        if ([aName isEqualToString:UIScreenCapturedDidChangeNotification]) return;
    } else {
        // Fallback on earlier versions
    }
    CHSuper4(NSNotificationCenter, addObserver, arg1, selector, aSelector, name, aName, object, anObject);
}
CHConstructor{
    CHLoadLateClass(NSNotificationCenter);
    CHClassHook4(NSNotificationCenter, addObserver, selector, name, object);
}
CHDeclareClass(UIScreen)
CHOptimizedMethod0(self, BOOL, UIScreen, isCaptured){
    return false;
}
CHConstructor{
    CHLoadLateClass(UIScreen);
    CHClassHook0(UIScreen, isCaptured);
}

#pragma mark 关闭过期校验
CHDeclareClass(APPExpiredView)
CHOptimizedMethod0(self, void, APPExpiredView, show){
//    CHSuper0(APPExpiredView, show);
}

CHConstructor{
    CHLoadLateClass(APPExpiredView);
    CHClassHook0(APPExpiredView, show);
}
//-----------------------------------
CHDeclareClass(TLRouter)
CHClassMethod2(void, TLRouter, pushToWatchLiveVcWithLiveModel, id, arg1, navigationController, id, arg2){
    CHSuper2(TLRouter, pushToWatchLiveVcWithLiveModel, arg1, navigationController, arg2);
}

CHConstructor{
    CHLoadLateClass(TLRouter);
//    CHClassHook0(TLWatchLiveVC, init);
    CHClassHook2(TLRouter, pushToWatchLiveVcWithLiveModel,navigationController);
}
//-----------------------------------
CHDeclareClass(TLWatchLiveVC)
CHOptimizedMethod1(self, void, TLWatchLiveVC, setupWithLiveModel, NSObject*, arg1){
    NSObject* model = nil;
    if ([arg1 respondsToSelector:@selector(liveDtoModel)]) {
        model = [arg1 performSelector:@selector(liveDtoModel)];
    }
    invocationInstanceValue(model,@"setChargeType:",0);
    CHSuper1(TLWatchLiveVC, setupWithLiveModel, arg1);
}
CHOptimizedMethod1(self, void, TLWatchLiveVC, showChargeWithOutAccessMaskModle, NSObject*, arg1){
    invocationInstanceValue(arg1,@"setNeedBuyTicket:",0);
    invocationInstanceValue(arg1,@"setChargeType:",0);
    invocationInstanceValue(arg1,@"setTicketPrice:",0);
    
    UIViewController* vc = self;
    UIView* view = vc.view;
    [[view viewWithTag:100] removeFromSuperview];
    UIButton* btn = [[UIButton alloc] init];
    btn.tag = 100;
    [btn setTitle:@"back" forState:UIControlStateNormal];
    CGSize size = [btn sizeThatFits:[UIScreen mainScreen].bounds.size];
    size.width += 10*2;
    [btn drawBounderWidth:2 radius:size.height/2 Color:[UIColor redColor].CGColor];
    [view addSubview:btn];
    btn.frame = CGRectMake(0, UIView.commonFaceIdSafeTop, size.width, size.height);
    @weakify(vc);
    [[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        @strongify(vc);
        invokeSelector(vc,@"leaveRoom");
    }];
    //CHSuper1(TLWatchLiveVC, showChargeWithOutAccessMaskModle, arg1);
}
CHOptimizedMethod1(self, void, TLWatchLiveVC, setMaskViewWithUrl, NSObject*, arg1){
    CHSuper1(TLWatchLiveVC, setMaskViewWithUrl, arg1);
}
CHOptimizedMethod0(self, UIView*, TLWatchLiveVC, contentVc){
    return  CHSuper0(TLWatchLiveVC, contentVc);
}
CHOptimizedMethod0(self, UIView*, TLWatchLiveVC, liveChargeMaskView){
    UIView* view = CHSuper0(TLWatchLiveVC, liveChargeMaskView);
    invocationInstanceValue(view,@"setRoomChargeType:",0);
//    invokeSelector(view,@"hiddenView");
    return view;
}
CHConstructor{
    CHLoadLateClass(TLWatchLiveVC);
    CHClassHook0(TLWatchLiveVC, liveChargeMaskView);
    CHClassHook0(TLWatchLiveVC, contentVc);
    CHClassHook1(TLWatchLiveVC, setupWithLiveModel);
    CHClassHook1(TLWatchLiveVC, showChargeWithOutAccessMaskModle);
    CHClassHook1(TLWatchLiveVC, setMaskViewWithUrl);
}

//-----------------------------------

CHDeclareClass(WTPersonCerService)
CHClassMethod1(id, WTPersonCerService, getUDIDUrl, id, arg1){
    NSString* text = CHSuper1(WTPersonCerService, getUDIDUrl, arg1);
    return text;
}
CHConstructor{
    CHLoadLateClass(WTPersonCerService);
    CHClassHook1(WTPersonCerService, getUDIDUrl);
}
//-----------------------------------
//CHDeclareClass(TLNetworkManager)
//CHOptimizedMethod3(self, void, TLNetworkManager, requestWithReqModel, id, arg1, succ, id, arg2, fail, id, arg3){
//    CHSuper3(TLNetworkManager, requestWithReqModel, arg1, succ, arg2, fail, arg3);
//}
//CHConstructor{
//    CHLoadLateClass(TLNetworkManager);
//    CHClassHook3(TLNetworkManager, requestWithReqModel,succ,fail);
//}
//-----------------------------------
CHDeclareClass(TLBaseReqModel)
CHOptimizedMethod1(self, id, TLBaseReqModel, reformToReultModel,id,arg1){
    NSDictionary* a = CHSuper1(TLBaseReqModel, reformToReultModel,arg1);
    DLog(@"%@",a);
    return a;
}
CHConstructor{
    CHLoadLateClass(TLBaseReqModel);
    CHClassHook1(TLBaseReqModel, reformToReultModel);
}

//-----------------------------------
CHDeclareClass(TLUserInfoReqModel)
CHOptimizedMethod0(self, id, TLUserInfoReqModel, init){
    return CHSuper0(TLUserInfoReqModel, init);
}

CHOptimizedMethod0(self, id, TLUserInfoReqModel, isLogin){
    id a = CHSuper0(TLUserInfoReqModel, isLogin);
    return a;
}

CHConstructor{
    CHLoadLateClass(TLUserInfoReqModel);
    CHClassHook0(TLUserInfoReqModel, init);
    CHClassHook0(TLUserInfoReqModel, isLogin);
}


//-----------------------------------
CHDeclareClass(WTMainTabBarController)
CHOptimizedMethod0(self, void, WTMainTabBarController, showLogin){
    CHSuper0(WTMainTabBarController, showLogin);
}

CHConstructor{
    CHLoadLateClass(WTMainTabBarController);
    CHClassHook0(WTMainTabBarController, showLogin);
}


#pragma mark -
#pragma mark -  爱奇艺
//====================================================================
//====================================================================
//开屏广告
CHDeclareClass(QYStartADView)
CHOptimizedMethod0(self, void, QYStartADView, timerStart){
    invokeSelector(self,@"skipAd");
}
CHConstructor{
    CHLoadLateClass(QYStartADView);
    CHClassHook0(QYStartADView, timerStart);
}

//====================================================================
//前贴广告
CHDeclareClass(PumaPlayerViewController)
CHOptimizedMethod1(self, void, PumaPlayerViewController, handleAdCallbackShow,id,arg1){
    CHSuper1(PumaPlayerViewController, handleAdCallbackShow,arg1);
}
CHOptimizedMethod0(self, void, PumaPlayerViewController, OnAdPrepared){
//    CHSuper0(PumaPlayerViewController, OnAdPrepared);
}
CHOptimizedMethod0(self, void, PumaPlayerViewController, logAdsModelToFile){
//        CHSuper0(PumaPlayerViewController, OnAdPrepared);
}
CHOptimizedMethod0(self, void, PumaPlayerViewController, initAdsProperties){
//        CHSuper0(PumaPlayerViewController, OnAdPrepared);
}
CHOptimizedMethod1(self, void, PumaPlayerViewController, parseAdsWithAdsContent,id,arg1){
//    CHSuper1(PumaPlayerViewController, parseAdsWithAdsContent,nil);
}
CHOptimizedMethod3(self, void, PumaPlayerViewController, initCupidIfcWithDic,id,arg1,playBackScene,int,arg2,isReopenFromAudioMode,bool,arg3){
    //    CHSuper1(PumaPlayerViewController, parseAdsWithAdsContent,nil);
}

CHConstructor{
    CHLoadLateClass(PumaPlayerViewController);
    CHClassHook1(PumaPlayerViewController, handleAdCallbackShow);
    CHClassHook1(PumaPlayerViewController, parseAdsWithAdsContent);
    CHClassHook0(PumaPlayerViewController, OnAdPrepared);
    CHClassHook0(PumaPlayerViewController, logAdsModelToFile);
    CHClassHook0(PumaPlayerViewController, initAdsProperties);
    
    CHClassHook3(PumaPlayerViewController, initCupidIfcWithDic,playBackScene,isReopenFromAudioMode);
}
//====================================================================

#pragma mark -
#pragma mark -  腾讯视频
//====================================================================
//#pragma mark - 去广告生效代码
//CHDeclareClass(TVKMediaPlayerManager)
//CHOptimizedMethod0(self, void, TVKMediaPlayerManager, prepareAdInfo){
//    return;
//}
//CHConstructor{
//    CHLoadLateClass(TVKMediaPlayerManager);
//    CHClassHook0(TVKMediaPlayerManager, prepareAdInfo);
//}
//#pragma mark -
//CHDeclareClass(AppUtils)
//CHClassMethod0(id, AppUtils, bundleID){
//    id dict = CHSuper0(AppUtils, bundleID);
//    return dict;//@"com.tencent.live4iphone";
//}
//CHConstructor{
//    CHLoadLateClass(AppUtils);
//    CHClassHook0(AppUtils, bundleID);
//}
//
//CHDeclareClass(QADCoreDeviceUtils)
//CHClassMethod0(id, QADCoreDeviceUtils, appBundleName){
//    id dict = CHSuper0(QADCoreDeviceUtils, appBundleName);
//    return dict;
//}
//CHConstructor{
//    CHLoadLateClass(QADCoreDeviceUtils);
//    CHClassHook0(QADCoreDeviceUtils, appBundleName);
//}
//#pragma mark -
//CHDeclareClass(QLDataKeyAdDetailModelCtl)
//CHOptimizedMethod0(self, id, QLDataKeyAdDetailModelCtl, adModel){
//    return nil;
//}
//CHConstructor{
//    CHLoadLateClass(QLDataKeyAdDetailModelCtl);
//    CHClassHook0(QLDataKeyAdDetailModelCtl, adModel);
//}
//#pragma mark -
//CHDeclareClass(QNBQQPlayerPlugin)
//CHOptimizedMethod0(self, id, QNBQQPlayerPlugin, imageAdsView){
//    return nil;
//}
//CHOptimizedMethod0(self, id, QNBQQPlayerPlugin, videoAdsView){
//    return nil;
//}
//CHConstructor{
//    CHLoadLateClass(QNBQQPlayerPlugin);
//    CHClassHook0(QNBQQPlayerPlugin, imageAdsView);
//    CHClassHook0(QNBQQPlayerPlugin, videoAdsView);
//}
//#pragma mark -
//CHDeclareClass(QLVideoDetailViewController)
//CHOptimizedMethod1(self, void , QLVideoDetailViewController, viewDidAppear,BOOL,arg1)
//{
//    CHSuper1(QLVideoDetailViewController, viewDidAppear, arg1);
//}
//
//CHOptimizedMethod3(self, id , QLVideoDetailViewController, tableView,UITableView*,arg1,willDisplayCell,id,cell,forRowAtIndexPath,id,indexpath){
//    //self->_detailModelPD->_adModelCtl->_adModel = nil;
//    id a = CHSuper3(QLVideoDetailViewController, tableView, arg1, willDisplayCell, cell, forRowAtIndexPath, indexpath);
//    return a;
//}
//
//CHConstructor{
//    CHLoadLateClass(QLVideoDetailViewController);
//    CHClassHook1(QLVideoDetailViewController, viewDidAppear);
//    CHClassHook3(QLVideoDetailViewController, tableView,willDisplayCell,forRowAtIndexPath);
////    CHClassHook5(ACAFHTTPSessionManager, GET, parameters, progress,success,failure);
//}

#pragma mark -
#pragma mark -  抖音
//====================================================================
CHDeclareClass(UIViewController)

CHOptimizedMethod3(self, void, UIViewController, presentViewController, UIViewController*, arg1, animated, BOOL, arg2,completion, id, arg3){
    
    if([arg1 isKindOfClass:UIAlertController.class]){
        UIAlertController* alert = arg1;
        if([alert.title containsString:@"官方版本"]){
            return;
        }
        CHSuper3(UIViewController,presentViewController,arg1,animated, arg2, completion,arg3);
    }
    else{
        CHSuper3(UIViewController,presentViewController,arg1,animated, arg2, completion,arg3);
    }
}

CHConstructor{
    CHLoadLateClass(UIViewController);
    CHClassHook3(UIViewController, presentViewController, animated, completion);
    
}

#pragma mark -
#pragma mark -  百度
//====================================================================
//渲染容器 slaveWebView
CHDeclareClass(SWANSlaveWebViewController)
CHOptimizedMethod3(self, void, SWANSlaveWebViewController, webView, id, arg1, decidePolicyForNavigationAction, id, arg2, decisionHandler, id, arg3)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg3] blockSignature];
    DLog(@"decidePolicyForNavigationAction \n arg1:%@ \n arg2:%@ \n arg3:%@ \n arg4:%@ ",arg1,arg2,arg3,[signature description]);
    CHSuper3(SWANSlaveWebViewController, webView, arg1, decidePolicyForNavigationAction, arg2, decisionHandler, arg3);
}

CHOptimizedMethod3(self, void, SWANSlaveWebViewController, webView, id, arg1, decidePolicyForNavigationResponse, id, arg2, decisionHandler, id, arg3)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg3] blockSignature];
    DLog(@"decidePolicyForNavigationResponse \n arg1:%@ \n arg2:%@ \n arg3:%@ \n arg4:%@ ",arg1,arg2,arg3,[signature description]);
    CHSuper3(SWANSlaveWebViewController, webView, arg1, decidePolicyForNavigationResponse, arg2, decisionHandler, arg3);
}

CHOptimizedMethod4(self, void, SWANSlaveWebViewController, webView, id, arg1, runJavaScriptConfirmPanelWithMessage, id, arg2, initiatedByFrame, id, arg3, completionHandler, id, arg4)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg4] blockSignature];
    DLog(@"runJavaScriptConfirmPanelWithMessage \n arg1:%@ \n arg2:%@ \n arg3:%@ \n arg4:%@ ",arg1,arg2,arg3,[signature description]);
    CHSuper4(SWANSlaveWebViewController, webView, arg1, runJavaScriptConfirmPanelWithMessage, arg2, initiatedByFrame, arg3, completionHandler, arg4);
}

CHOptimizedMethod4(self, void, SWANSlaveWebViewController, webView, id, arg1, runJavaScriptAlertPanelWithMessage, id, arg2, initiatedByFrame, id, arg3, completionHandler, id, arg4)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg4] blockSignature];
    DLog(@"runJavaScriptAlertPanelWithMessage \n arg1:%@ \n arg2:%@ \n arg3:%@ \n arg4:%@ ",arg1,arg2,arg3,[signature description]);
    CHSuper4(SWANSlaveWebViewController, webView, arg1, runJavaScriptAlertPanelWithMessage, arg2, initiatedByFrame, arg3, completionHandler, arg4);
}

CHOptimizedMethod5(self, void, SWANSlaveWebViewController, webView, id, arg1, runJavaScriptTextInputPanelWithPrompt, id, arg2, defaultText, id, arg3, initiatedByFrame, id, arg4,completionHandler, id, arg5)
{

    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg5] blockSignature];
    DLog(@"runJavaScriptTextInputPanelWithPrompt\n arg1:%@ \n arg2:%@ \n arg3:%@ \n arg4:%@ \n arg5:%@",arg1,arg2,arg3,arg4,[signature description]);
    CHSuper5(SWANSlaveWebViewController, webView, arg1, runJavaScriptTextInputPanelWithPrompt, arg2, defaultText, arg3, initiatedByFrame, arg4,completionHandler, arg5);
}

CHOptimizedMethod2(self, void, SWANSlaveWebViewController, dispatchToSlaveEventJS, id, arg1, completionHandler, id, arg2)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg2] blockSignature];
    DLog(@"dispatchToSlaveEventJS \n arg1:%@ \n arg2:%@ ",arg1,[signature description]);
    CHSuper2(SWANSlaveWebViewController, dispatchToSlaveEventJS, arg1, completionHandler, arg2);
}

CHOptimizedMethod3(self, void, SWANSlaveWebViewController, dispatchToSlaveEventName, id, arg1, eventParam, id, arg2, completionHandler, id, arg3)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg3] blockSignature];
    DLog(@"dispatchToSlaveEventName \n arg1:%@ \n arg2:%@ \n arg3:%@ ",arg1,arg2,[signature description]);
    CHSuper3(SWANSlaveWebViewController, dispatchToSlaveEventName, arg1, eventParam, arg2, completionHandler,arg3);
}

CHOptimizedMethod4(self, id, SWANSlaveWebViewController, webView, id, arg1, createWebViewWithConfiguration, id, arg2, forNavigationAction, id, arg3, windowFeatures, id, arg4)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg4] blockSignature];
    DLog(@"createWebViewWithConfiguration \n arg1:%@ \n arg2:%@ \n arg3:%@ \n arg4:%@ ",arg1,arg2,arg3,[signature description]);
    return CHSuper4(SWANSlaveWebViewController, webView, arg1, createWebViewWithConfiguration, arg2, forNavigationAction, arg3, windowFeatures, arg4);
}

CHOptimizedMethod2(self, void, SWANSlaveWebViewController, webView, id, arg1, didFinishNavigation, id, arg2)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg2] blockSignature];
    DLog(@"didFinishNavigation \n arg1:%@ \n arg2:%@ ",arg1,[signature description]);
    CHSuper2(SWANSlaveWebViewController, webView, arg1, didFinishNavigation, arg2);
}


CHConstructor{
    CHLoadLateClass(SWANSlaveWebViewController);
    CHClassHook3(SWANSlaveWebViewController, webView,decidePolicyForNavigationAction, decisionHandler);
    CHClassHook3(SWANSlaveWebViewController, webView,decidePolicyForNavigationResponse, decisionHandler);
    CHClassHook4(SWANSlaveWebViewController, webView,runJavaScriptConfirmPanelWithMessage, initiatedByFrame, completionHandler);
    CHClassHook4(SWANSlaveWebViewController, webView,runJavaScriptAlertPanelWithMessage, initiatedByFrame, completionHandler);
    CHClassHook5(SWANSlaveWebViewController, webView,runJavaScriptTextInputPanelWithPrompt, defaultText, initiatedByFrame,completionHandler);
    CHClassHook2(SWANSlaveWebViewController, dispatchToSlaveEventJS,completionHandler);
    CHClassHook3(SWANSlaveWebViewController, dispatchToSlaveEventName,eventParam, completionHandler);

    CHClassHook4(SWANSlaveWebViewController, webView,createWebViewWithConfiguration, forNavigationAction, windowFeatures);
    CHClassHook2(SWANSlaveWebViewController, webView,didFinishNavigation);
}
//====================================================================
CHDeclareClass(SWANApp)
CHOptimizedMethod3(self, void, SWANApp, dispatchToMasterLifeCycleName, id, arg1, eventParam, id, arg2, completionHandler, id, arg3)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg3] blockSignature];
    DLog(@"dispatchToMasterLifeCycleName \n arg1:%@ \n arg2:%@ \n arg3:%@ ",arg1,arg2,[signature description]);
    CHSuper3(SWANApp, dispatchToMasterLifeCycleName, arg1, eventParam, arg2, completionHandler,arg3);
}

CHOptimizedMethod3(self, void, SWANApp, dispatchToMasterEventName, id, arg1, eventParam, id, arg2, completionHandler, id, arg3)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg3] blockSignature];
    DLog(@"dispatchToMasterEventName \n arg1:%@ \n arg2:%@ \n arg3:%@ ",arg1,arg2,[signature description]);
    CHSuper3(SWANApp, dispatchToMasterEventName, arg1, eventParam, arg2, completionHandler,arg3);
}

CHOptimizedMethod2(self, void, SWANApp, dispatchToMasterEventJS, id, arg1, completionHandler, id, arg2)
{
    NSMethodSignature *signature = nil;//[[[CTBlockDescription alloc]initWithBlock:arg2] blockSignature];
    DLog(@"dispatchToMasterEventJS \n arg1:%@ \n arg2:%@ ",arg1,[signature description]);
    CHSuper2(SWANApp, dispatchToMasterEventJS, arg1, completionHandler, arg2);
}

CHConstructor{
    CHLoadLateClass(SWANApp);
    CHClassHook3(SWANApp, dispatchToMasterLifeCycleName,eventParam, completionHandler);
    CHClassHook3(SWANApp, dispatchToMasterEventName,eventParam, completionHandler);
    CHClassHook2(SWANApp, dispatchToMasterEventJS,completionHandler);
}

//====================================================================
CHDeclareClass(BBAMNPJSBridge)
CHOptimizedMethod2(self, void, BBAMNPJSBridge, userContentController, WKUserContentController*, arg1, didReceiveScriptMessage, WKScriptMessage*, arg2)
{
    
    DLog(@"arg1:%@ \n name:%@ \n body:%@ \n",arg1,arg2.name,arg2.body);
    CHSuper2(BBAMNPJSBridge, userContentController, arg1, didReceiveScriptMessage, arg2);
}

CHConstructor{
    CHLoadLateClass(BBAMNPJSBridge);
    CHClassHook2(BBAMNPJSBridge, userContentController,didReceiveScriptMessage);
}
//====================================================================
CHDeclareClass(WKWebView)
CHOptimizedMethod2(self, void, WKWebView, evaluateJavaScript, NSString*, arg1, completionHandler, id, arg2)
{
    
    DLog(@"arg1:%@ \n arg2:%@ \n",arg1,arg2);
    CHSuper2(WKWebView, evaluateJavaScript, arg1, completionHandler, arg2);
}

CHConstructor{
    CHLoadLateClass(WKWebView);
    CHClassHook2(WKWebView, evaluateJavaScript,completionHandler);
}


#pragma mark -
#pragma mark -  demo
//====================================================================

CHDeclareClass(CustomViewController)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wstrict-prototypes"

//add new method
CHDeclareMethod1(void, CustomViewController, newMethod, NSString*, output){
    DLog(@"This is a new method : %@", output);
}

#pragma clang diagnostic pop

CHOptimizedClassMethod0(self, void, CustomViewController, classMethod){
    DLog(@"hook class method");
    CHSuper0(CustomViewController, classMethod);
}

CHOptimizedMethod0(self, NSString*, CustomViewController, getMyName){
    //get origin value
    NSString* originName = CHSuper(0, CustomViewController, getMyName);
    
    DLog(@"origin name is:%@",originName);
    
    //get property
    NSString* password = CHIvar(self,_password,__strong NSString*);
    
    DLog(@"password is %@",password);
    
    [self newMethod:@"output"];
    
    //set new property
    self.newProperty = @"newProperty";
    
    DLog(@"newProperty : %@", self.newProperty);
    
    //change the value
    return @"111";
    
}

//add new property
CHPropertyRetainNonatomic(CustomViewController, NSString*, newProperty, setNewProperty);

CHConstructor{
    CHLoadLateClass(CustomViewController);
    CHClassHook0(CustomViewController, getMyName);
    CHClassHook0(CustomViewController, classMethod);
    
    CHHook0(CustomViewController, newProperty);
    CHHook1(CustomViewController, setNewProperty);
}



#pragma clang diagnostic pop
